package com.newshub.logging.implementation.file;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 日志文件滚动器
 * 负责日志文件的滚动、清理和归档
 */
@Slf4j
@Component
public class FileLogRotator {
    
    @Value("${logging.storage.file.path:logs}")
    private String logPath;
    
    @Value("${logging.storage.file.prefix:news-hub}")
    private String logPrefix;
    
    @Value("${logging.storage.file.max-size:100MB}")
    private String maxSize;
    
    @Value("${logging.storage.file.max-count:10}")
    private int maxCount;
    
    @Value("${logging.storage.file.max-history:30}")
    private int maxHistory;
    
    private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    
    /**
     * 检查并滚动日志文件
     */
    public void checkAndRotate(String currentFileName) {
        try {
            Path filePath = Paths.get(currentFileName);
            if (Files.exists(filePath)) {
                long fileSize = Files.size(filePath);
                long maxSizeBytes = parseSize(maxSize);
                
                if (fileSize > maxSizeBytes) {
                    rotateFile(currentFileName);
                }
            }
        } catch (IOException e) {
            log.error("检查日志文件滚动失败: {}", currentFileName, e);
        }
    }
    
    /**
     * 滚动日志文件
     */
    private void rotateFile(String currentFileName) throws IOException {
        Path filePath = Paths.get(currentFileName);
        String baseName = currentFileName.substring(0, currentFileName.lastIndexOf('.'));
        String extension = currentFileName.substring(currentFileName.lastIndexOf('.'));
        
        // 查找下一个可用的序号
        int nextIndex = 0;
        String newFileName;
        do {
            newFileName = baseName + "." + nextIndex + extension;
            nextIndex++;
        } while (Files.exists(Paths.get(newFileName)));
        
        // 重命名文件
        Files.move(filePath, Paths.get(newFileName));
        log.info("日志文件已滚动: {} -> {}", currentFileName, newFileName);
        
        // 清理旧文件
        cleanupOldFiles();
    }
    
    /**
     * 清理过期日志文件
     * 每天凌晨2点执行
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void cleanupExpiredLogs() {
        try {
            log.info("开始清理过期日志文件...");
            
            Path logDir = Paths.get(logPath);
            if (!Files.exists(logDir)) {
                return;
            }
            
            // 获取所有日志文件
            List<Path> logFiles = Files.list(logDir)
                    .filter(path -> path.toString().contains(logPrefix))
                    .filter(path -> path.toString().endsWith(".log"))
                    .collect(Collectors.toList());
            
            // 按修改时间排序
            logFiles.sort(Comparator.comparing(path -> {
                try {
                    return Files.getLastModifiedTime(path).toMillis();
                } catch (IOException e) {
                    return 0L;
                }
            }));
            
            // 删除超过保留天数的文件
            LocalDateTime cutoffDate = LocalDateTime.now().minusDays(maxHistory);
            int deletedCount = 0;
            
            for (Path logFile : logFiles) {
                try {
                    LocalDateTime fileDate = LocalDateTime.parse(
                            extractDateFromFileName(logFile.getFileName().toString()),
                            dateFormatter
                    );
                    
                    if (fileDate.isBefore(cutoffDate)) {
                        Files.delete(logFile);
                        deletedCount++;
                        log.info("删除过期日志文件: {}", logFile);
                    }
                } catch (Exception e) {
                    log.warn("无法解析日志文件日期: {}", logFile, e);
                }
            }
            
            log.info("过期日志文件清理完成，删除了 {} 个文件", deletedCount);
            
        } catch (Exception e) {
            log.error("清理过期日志文件失败", e);
        }
    }
    
    /**
     * 清理旧文件（按数量限制）
     */
    private void cleanupOldFiles() {
        try {
            Path logDir = Paths.get(logPath);
            if (!Files.exists(logDir)) {
                return;
            }
            
            // 获取当前日期的所有日志文件
            String today = LocalDateTime.now().format(dateFormatter);
            String todayPrefix = logPrefix + "-" + today;
            
            List<Path> todayLogFiles = Files.list(logDir)
                    .filter(path -> path.toString().contains(todayPrefix))
                    .filter(path -> path.toString().endsWith(".log"))
                    .collect(Collectors.toList());
            
            // 如果文件数量超过限制，删除最旧的文件
            if (todayLogFiles.size() > maxCount) {
                todayLogFiles.sort(Comparator.comparing(path -> {
                    try {
                        return Files.getLastModifiedTime(path).toMillis();
                    } catch (IOException e) {
                        return 0L;
                    }
                }));
                
                int filesToDelete = todayLogFiles.size() - maxCount;
                for (int i = 0; i < filesToDelete; i++) {
                    Path fileToDelete = todayLogFiles.get(i);
                    Files.delete(fileToDelete);
                    log.info("删除旧日志文件: {}", fileToDelete);
                }
            }
            
        } catch (Exception e) {
            log.error("清理旧日志文件失败", e);
        }
    }
    
    /**
     * 从文件名中提取日期
     */
    private String extractDateFromFileName(String fileName) {
        // 文件名格式: news-hub-2025-08-23.log 或 news-hub-2025-08-23.0.log
        int startIndex = fileName.indexOf("-") + 1;
        int endIndex = fileName.lastIndexOf(".");
        if (endIndex == -1) {
            endIndex = fileName.length();
        }
        
        String datePart = fileName.substring(startIndex, endIndex);
        // 如果包含序号，去掉序号部分
        if (datePart.contains(".")) {
            datePart = datePart.substring(0, datePart.lastIndexOf("."));
        }
        
        return datePart;
    }
    
    /**
     * 解析文件大小字符串
     */
    private long parseSize(String sizeStr) {
        sizeStr = sizeStr.toUpperCase();
        if (sizeStr.endsWith("KB")) {
            return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 2)) * 1024;
        } else if (sizeStr.endsWith("MB")) {
            return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024;
        } else if (sizeStr.endsWith("GB")) {
            return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 2)) * 1024 * 1024 * 1024;
        } else {
            return Long.parseLong(sizeStr);
        }
    }
}
